package com.alogic.together2.xscript;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Random;
import javax.imageio.ImageIO;
import org.apache.commons.lang3.StringUtils;
import com.alogic.xscript.AbstractLogiclet;
import com.alogic.xscript.ExecuteWatcher;
import com.alogic.xscript.Logiclet;
import com.alogic.xscript.LogicletContext;
import com.alogic.xscript.doc.XsObject;
import com.anysoft.util.BaseException;
import com.anysoft.util.Properties;
import com.anysoft.util.PropertiesConstants;
import com.anysoft.util.Settings;
import com.logicbus.backend.Context;
import com.logicbus.backend.server.http.HttpCacheTool;

/**
 * 图片验证码
 * @author yyduan
 * @since 1.6.12.2
 */
public class ImageCode extends AbstractLogiclet{
	protected String pid = "$context";
	protected String $content = "";
	protected String $cacheEnable = "false";
	protected String $filename = "";
	protected String $contentType = "image/jpeg";
	protected HttpCacheTool cacheTool = null;
	protected String encoding = "utf-8";
	protected String $width = "80";
	protected String $height = "26";
	/**
	 * 干扰线的数量
	 */
	private String $disturbanceLines = "40";
	
	protected String id;
	/**
	 * 字体
	 */
	private Font font = null;	
	
	/**
	 * 随机数发生器
	 */
    private Random random = new Random();	
	
	public ImageCode(String tag, Logiclet p) {
		super(tag, p);
	}
	
	@Override
	public void configure(Properties p){
		super.configure(p);
		
		pid = PropertiesConstants.getString(p,"pid",pid,true);
		$cacheEnable = PropertiesConstants.getRaw(p, "cacheEnable", $cacheEnable);
		$width = PropertiesConstants.getRaw(p, "width", $width);
		$height = PropertiesConstants.getRaw(p, "height", $height);
		$filename = PropertiesConstants.getRaw(p, "filename", $filename);
		$contentType = PropertiesConstants.getRaw(p, "contentType", $contentType);
		$content = PropertiesConstants.getRaw(p, "content", $content);
		$disturbanceLines = PropertiesConstants.getRaw(p, "disturbanceLines", $disturbanceLines);
		cacheTool = Settings.getToolkit(HttpCacheTool.class);
		encoding = PropertiesConstants.getString(p,"encoding",encoding);
		id = PropertiesConstants.getString(p,"id","$" + getXmlTag(),true);
		font = new Font(PropertiesConstants.getString(p, "text.font", "Liberation Serif",true),Font.CENTER_BASELINE,18);	
	}

	@Override
	protected void onExecute(XsObject root, XsObject current,
			final LogicletContext ctx, final ExecuteWatcher watcher) {
		Context serviceContext = ctx.getObject(pid);
		if (serviceContext == null) {
			throw new BaseException("core.e1001",
					"It must be in a DownloadTogetherServant servant,check your together script.");
		}

		if (PropertiesConstants.transform(ctx, $cacheEnable, true)) {
			cacheTool.cacheEnable(serviceContext);
		} else {
			cacheTool.cacheDisable(serviceContext);
		}

		String filename = PropertiesConstants.transform(ctx, $filename, "");
		if (StringUtils.isNotEmpty(filename)) {
			try {
				filename = URLEncoder.encode(filename, encoding);
			} catch (UnsupportedEncodingException e) {
			}
			serviceContext.setResponseHeader("Content-Disposition", String
					.format("attachment; filename=%s;filename*=%s''%s",
							filename, encoding, filename));
		}

		String contentType = PropertiesConstants.transform(ctx, $contentType,
				"");
		if (StringUtils.isNotEmpty(contentType)) {
			serviceContext.setResponseContentType(contentType);
		}

		String content = PropertiesConstants.transform(ctx, $content, "");

		if (StringUtils.isEmpty(content)) {
			throw new BaseException("core.e1003","The content of image code is null");
		}

		int width = PropertiesConstants.getInt(ctx, $width, 80);
		int height = PropertiesConstants.getInt(ctx, $height, 26);
		int disturbanceLines = PropertiesConstants.getInt(ctx, $disturbanceLines, 26);
		try {
			OutputStream out = serviceContext.getOutputStream();

			BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_BGR);
			Graphics g = image.getGraphics();
			g.fillRect(0, 0, width, height);
			g.setFont(font == null ? new Font("Fixedsys",Font.CENTER_BASELINE,18) : font);
			g.setColor(getRandColor(110, 133));
			
			//绘制干扰线
	        for(int i=0;i<=disturbanceLines;i++){
	            drowLine(g,width,height);
	        }
	        
	        //绘制code
	        for (int i = 0 ;i < content.length() ; i ++){
	        	drowString(g,String.valueOf(content.charAt(i)),i);
	        }
	        //完成
	        g.dispose();
	        
	        ImageIO.write(image, "JPEG", out);

			out.flush();
			ctx.SetValue(id, "true");
		} catch (Exception ex) {
			log("Error when writing data to outputstream:" + ex.getMessage(), LOG_ERROR,ctx);
			ctx.SetValue(id, "false");
		}
	}
	
    private void drowLine(Graphics g,int width,int height) {
        int x = random.nextInt(width);
        int y = random.nextInt(height);
        int xl = random.nextInt(13);
        int yl = random.nextInt(15);
        g.drawLine(x, y, x+xl, y+yl);
	}

    private void drowString(Graphics g,String randomString,int i){
        g.translate(random.nextInt(3), random.nextInt(3));
        g.drawString(randomString, 13*i, 16);
    }
    
	private Color getRandColor(int fc,int bc){
        if(fc > 255)
            fc = 255;
        if(bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc-fc-16);
        int g = fc + random.nextInt(bc-fc-14);
        int b = fc + random.nextInt(bc-fc-18);
        return new Color(r,g,b);
    }	
}
